package com.wujian.love.controller;

import cn.hutool.core.date.DateTime;
import com.wujian.love.redis.RedisKey;
import com.wujian.love.redis.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

/**
 * @ClassName: RedisSignController
 * @Description: 使用reids 的位图数据  进行签到功能的实现
 * @Author: wuj
 * @Date: 2021-01-13 11:28
 **/
@RestController
@RequestMapping("/redis")
public class RedisSignController {

    private static final DateTime dateTime = new DateTime();

    @Autowired
    private RedisService redisService;


    @GetMapping("/sign")
    public void  sign(Long userId) {
        String key = RedisKey.getSignKey(userId);
        UUID.randomUUID();
        //获取当前日期并减一
        int offset = dateTime.dayOfMonth() - 1;
        //判断当前是否已经签到
        Boolean flag = redisService.getbit(key, offset);
        //如果没有签到
        if(!flag){
            //签到
            redisService.setbit(key,offset,true);
        }
        //获取用户的签到次数
        Long count  = redisService.bitcount(key);
        System.out.println("用户签到次数:"+count);
        //获取当月连续签到次数
        long continuousSignCount = getContinuousSignCount(key, dateTime.dayOfMonth());
        System.out.println("当月的签到数:"+continuousSignCount);

        Map<String, Boolean> signInfo = getSignInfo(key, dateTime.dayOfMonth());
        System.out.println("当月的签到情况:"+signInfo.toString());
    }




    /**
     * 获取当月连续签到次数
     */
    long getContinuousSignCount(String key,int date) {
        int signCount = 0;
        String type = String.format("u%d", date);
        List<Long> list = redisService.bitfield(key, "GET", type, "0");
        if (list != null && list.size() > 0) {
            // 取低位连续不为0的个数即为连续签到次数，需考虑当天尚未签到的情况
            long v = list.get(0) == null ? 0 : list.get(0);
            for (int i = 0; i < date; i++) {
                if (v >> 1 << 1 == v) {
                    // 低位为0且非当天说明连续签到中断了
                    if (i > 0) {
                        break;
                    }
                } else {
                    signCount += 1;
                }
                v >>= 1;
            }
        }
        return signCount;
    }



    /**
     * 获取当月签到情况
     * @return Key为签到日期，Value为签到状态的Map
     */
   public Map<String, Boolean> getSignInfo(String key ,int date) {
        TreeMap<String, Boolean> signMap = new TreeMap<>();
        //获取当前一个月长度
        LocalDate today = LocalDate.now();
        String type = String.format("u%d", today.lengthOfMonth());
        List<Long> list = redisService.bitfield(key, "GET", type, "0");
        if (list != null && list.size() > 0) {
            // 由低位到高位，为0表示未签，为1表示已签
            long v = list.get(0) == null ? 0 : list.get(0);
            for (int i = today.lengthOfMonth(); i > 0; i--) {
                LocalDate d = today.withDayOfMonth(i);
                String format = d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                boolean b = v >> 1 << 1 != v;
                signMap.put(format, v >> 1 << 1 != v);
                v >>= 1;
            }
        }
        return signMap;
    }



}
